/**
 * @file    parallel.h
 * @brief   并机协议处理
 * @author  name
 * @version 1.0.1
 * @date    2023-05-05
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-05-05 <td>1.0.1     <td>name     <td>首次创建
 * </table>
 */

#ifndef __PARALLEL_H_
#define __PARALLEL_H_

/* file includes -------------------------------------------------------------*/
#include <stdint.h>
#include "diagnosis.h"
#include "cfg_prj.h"
/* cplusplus -----------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif

/* macro/define/typedef ------------------------------------------------------*/
#define PARALLEL_MASTER_ADDR   (1)     /* 并机状态主机地址 */
#define MASTER_TRAIN_CYCLE     (500)  /* 主机轮询周期 */
#define OL_TRY_TIMES           (1)
#define SLAVE_OL_OFF_TIMES     (3)
/* @brief 主机开机寄存器 */
#define M_REG_OPEN_START       (0)
#define M_REG_OPEN_END         (8)
#define M_REG_OPEN_SIZE        (8)
///* @brief 从机数据寄存器 */
#define S_SMP_DATA_START       (0)
#define S_SMP_DATA_END         (64)
#define S_SMP_DATA_SIZE        (58)
#define SLAVE_CELL_NUM         (16)  //不可更改
#define SLAVE_TEMP_NUM         (4)

enum
{
	PARALLEL_PCS_CHG_EN , 
	PARALLEL_PCS_DSG_EN ,
	PARALLEL_PCS_FROCE_CHG1 ,
	PARALLEL_PCS_FROCE_CHG2 ,
};

enum
{
	PAL_MODE_SW_RS485 = 0 ,
	PAL_MODE_SW_CAN   = 1 ,
	PAL_MODE_AUTO_RS485 = 2 ,
	PAL_MODE_AUTO_CAN = 3 ,
};
/**
 * @brief 自动标定状态
 */
typedef enum
{
    AUTO_ADDR_START ,    /*(00)启动 */
    AUTO_ADDR_RUNNING ,  /*(01)标定 */
    AUTO_ADDR_CMP   ,    /*(02)完成 */
}auto_addr_state_type;

#define ADDR_STATE_UNDEF     (0)     /* 寻址状态-未标定*/
#define ADDR_STATE_CFG       (1)     /* 寻址状态-已标定*/
#define RUN_STATE_NORMAL     (0x55)  /* 正常运行 */
#define RUN_STATE_AUTO_ADDR  (0x00)  /* 正在寻址 */
/* 串口自动寻址 */
#define COM_WAIT_DELAY       (3000)  /* 上电等待延时 mS */
#define COM_INIT_DELAY       (2000)
#define COM_TRY_DELAY        (200)   /* 尝试标定 */
#define COM_TIMEOUT          (1000)  /* 超时时间 */
#define COM_OVER_DELAY       (1000)   /* 结束命令延时 */

typedef struct
{
	uint8_t ol_state;
	uint8_t send_cnt;
	uint8_t recv_cnt;
}slave_ol_type;

typedef union 
{
	uint16_t prp_msg; 
	struct
	{
		uint16_t cov : 1;
		uint16_t cuv : 1;
		uint16_t ocd : 1;
		uint16_t ocd2 : 1;
		uint16_t occ : 1;
		uint16_t sc : 1;
		uint16_t bov : 1;
		uint16_t buv : 1;
		uint16_t col : 1;
		uint16_t afe_err : 1;
		uint16_t vdiff:1;
		uint16_t reverse:1;
		uint16_t full_chg:1;
	}name;
}slave_vlot_prp_type;

typedef union 
{
	uint16_t prp_msg;
	struct
	{
		uint16_t utc : 1;
		uint16_t otc : 1;
		uint16_t utd : 1;
		uint16_t otd : 1;
		uint16_t otm : 1;
		uint16_t ote : 1;
		uint16_t ute : 1;
		uint16_t cmos_ft :1;
		uint16_t dmos_ft :1;
		uint16_t tol : 1;
	}name;
}slave_temp_prp_type;

typedef union 
{
	uint16_t alm_msg;
	struct
	{
		uint32_t cov : 1 ;           /*!< (00)单体过高 */
        uint32_t cuv : 1 ;           /*!< (01)单体过低 */
		uint32_t ocd : 1 ;           /*!< (02)放电过流 */
		uint32_t occ : 1 ;           /*!< (03)充电过流 */
        uint32_t bov : 1 ;           /*!< (04)总压过高 */
        uint32_t buv : 1 ;           /*!< (05)总压过低 */
        uint32_t otc : 1 ;           /*!< (06)充电过温 */
        uint32_t utc : 1 ;           /*!< (07)充电欠温 */
        uint32_t otd : 1 ;           /*!< (08)放电过温 */
        uint32_t utd : 1 ;           /*!< (09)放电欠温 */
		uint32_t omtd : 1 ;          /*!< (10)MOS高温 */
		uint32_t socl:1;             /*!< (11)SOC过低 */
        uint32_t oetd : 1 ;          /*!< (12)环境高温 */
		uint32_t uetd : 1 ;          /*!< (13)环境低温 */
        uint32_t vdiff: 1 ;          /*!< (14)压差过大 */
        uint32_t tdiff: 1 ;          /*!< (15)温差过大 */
		uint16_t full_chg:1;
	}name;
}slave_alarm_type;

typedef struct auto_addr
{
    uint8_t addr_state;  // 地址状态
    uint8_t run_state;   // 运行状态 
    auto_addr_state_type auto_addr_state;
    uint8_t now_set_addr; // 当前标定地址
    uint16_t wait_dly_cnt ;
    uint16_t slave_chk_cnt;
    uint32_t send_dly_cnt;
    uint32_t init_dly_cnt;  // 初始检测延时
    uint32_t set_timeout_cnt; // 设置超时时间
}auto_addr_data_type;

#pragma pack(1)
/**
 * @brief 从机数据类型 
 */
typedef struct 
{
    uint16_t cell_num;
    uint16_t cell_volt_buf[SLAVE_CELL_NUM];
    uint16_t max_cell_volt;
    uint16_t min_cell_volt;
    uint16_t batt_volt;
    uint16_t curr_h16;
    uint16_t curr_l16;
    uint16_t max_temp;
    uint16_t min_temp;
    uint16_t full_cap;
    uint16_t real_cap;
    uint16_t cycle;
    uint16_t soc;
    uint16_t soh;
    slave_vlot_prp_type prp_volt_status;
    slave_temp_prp_type prp_temp_status;
    uint16_t fet_status;
    uint16_t alarm_status;
    uint16_t sn_code[15];
	uint16_t sop_cc;
	uint16_t sop_dc;
	uint16_t ver_test;
	uint16_t mos_temp;
	uint16_t env_temp;
	uint8_t version;
	uint8_t temp_num;
	uint16_t cell_temp_buf[SLAVE_TEMP_NUM];
}slave_data_type;

/**
 * @brief 并机主机数据类型
 */
typedef struct
{
	uint16_t cell_num;
	uint16_t parallel_num;
	uint16_t avg_cell_buf[16];
	uint16_t avg_max_volt;
	uint16_t avg_min_volt;
	uint16_t avg_batt_volt;
	int32_t total_bus_curr;  //0.01A 
	uint16_t avg_max_temp;
	uint16_t avg_min_temp;
	uint16_t avg_soc;
	uint16_t avg_soh;
	uint16_t avg_cycle;
	uint16_t com_err_state;
	uint16_t slave_prp_status;
	uint32_t total_full_cap;
	uint32_t total_std_cap;
	uint32_t total_stp_cap;
	uint32_t total_real_cap;
	diag_prp_type total_prp_msg;
	uint16_t max_volt_sn;
	uint16_t min_volt_sn;
	uint16_t max_temp_val;
	uint16_t min_temp_val;
	uint16_t max_temp_sn;
	uint16_t min_temp_sn;
	uint8_t fet_status;   /* B0:DSG B1:CHG*/
	uint16_t temp_num;
	uint16_t avg_temp_buf[SLAVE_TEMP_NUM];
	slave_data_type slave_data[CFG_PARALLEL_NUM];
}master_data_type;
#pragma pack()

/* variables -----------------------------------------------------------------*/
extern master_data_type master_data_reg;
extern slave_ol_type slave_ol_data[CFG_PARALLEL_NUM];
/*******************************************************************************
 * public API List
 ******************************************************************************/
void parallel_master_update_self(void);
void parallel_clear_slave(uint8_t slave);
void parallel_master_calc(void);
uint8_t parallel_bst_master_deal(uint16_t cycle , uint8_t *tx_buf ,uint16_t *tx_len);
uint16_t parallel_get_volt_prp_msg(void);
uint16_t parallel_get_temp_prp_msg(void);
uint16_t parallel_get_fet_status(void);
uint16_t parallel_get_alarm_status(void);
uint16_t parallel_get_sys_sign_msg(void);
uint16_t parallel_get_sys_mos_state(void);
uint8_t parallel_get_mode(void);
uint8_t parallel_is_master(void);
void parallel_pcs_deal(void);
uint8_t parallel_get_pcs_ctrl(uint8_t name);
void parallel_slave_update_self(uint16_t cycle);

#ifdef __cplusplus
}
#endif

#endif  /* #ifndef __PARALLEL_H_ */
